/*
 * Copyright [2022] [https://www.xiaonuo.vip]
 *
 * Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：
 *
 * 1.请不要删除和修改根目录下的LICENSE文件。
 * 2.请不要删除和修改Snowy源码头部的版权声明。
 * 3.本项目代码可免费商业使用，商业使用请保留源码和相关描述文件的项目出处，作者声明等。
 * 4.分发源码时候，请注明软件出处 https://www.xiaonuo.vip
 * 5.不可二次分发开源参与同类竞品，如有想法可联系团队xiaonuobase@qq.com商议合作。
 * 6.若您的项目无法满足以上几点，需要更多功能代码，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package vip.xiaonuo.biz.modular.approvalorder.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.xiaonuo.auth.core.pojo.SaBaseLoginUser;
import vip.xiaonuo.auth.core.util.StpLoginUserUtil;
import vip.xiaonuo.biz.modular.approval.entity.BizApproval;
import vip.xiaonuo.biz.modular.approval.enums.BizApprovalEnum;
import vip.xiaonuo.biz.modular.approval.service.BizApprovalService;
import vip.xiaonuo.biz.modular.approvalorder.entity.BizApprovalOrder;
import vip.xiaonuo.biz.modular.approvalorder.enums.BizApprovalCafeteriaTypeEnum;
import vip.xiaonuo.biz.modular.approvalorder.enums.BizApprovalPayTypeEnum;
import vip.xiaonuo.biz.modular.approvalorder.mapper.BizApprovalOrderMapper;
import vip.xiaonuo.biz.modular.approvalorder.param.*;
import vip.xiaonuo.biz.modular.approvalorder.result.BizApprovalCanteenResult;
import vip.xiaonuo.biz.modular.approvalorder.result.BizApprovalDeptResult;
import vip.xiaonuo.biz.modular.approvalorder.service.BizApprovalOrderService;
import vip.xiaonuo.biz.modular.canteen.entity.BizCanteen;
import vip.xiaonuo.biz.modular.canteen.service.BizCanteenService;
import vip.xiaonuo.common.enums.CommonSortOrderEnum;
import vip.xiaonuo.common.enums.CommonSwitchEnum;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.common.page.CommonPageRequest;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Objects;

/**
 * 签到支付记录Service接口实现类
 *
 * @author fqa
 * @date 2025/05/16 10:36
 **/
@Service
public class BizApprovalOrderServiceImpl extends ServiceImpl<BizApprovalOrderMapper, BizApprovalOrder> implements BizApprovalOrderService {

    @Override
    public Page<BizApprovalOrder> page(BizApprovalOrderPageParam bizApprovalOrderPageParam) {
        QueryWrapper<BizApprovalOrder> queryWrapper = new QueryWrapper<BizApprovalOrder>().checkSqlInjection();
        if (ObjectUtil.isNotEmpty(bizApprovalOrderPageParam.getApplicantId())) {
            queryWrapper.lambda().eq(BizApprovalOrder::getApplicantId, bizApprovalOrderPageParam.getApplicantId());
        }
        if (ObjectUtil.isNotEmpty(bizApprovalOrderPageParam.getVisitDeptId())) {
            queryWrapper.lambda().eq(BizApprovalOrder::getVisitDeptId, bizApprovalOrderPageParam.getVisitDeptId());
        }
        if (ObjectUtil.isNotEmpty(bizApprovalOrderPageParam.getVisitCafeteriaId())) {
            queryWrapper.lambda().eq(BizApprovalOrder::getVisitCafeteriaId, bizApprovalOrderPageParam.getVisitCafeteriaId());
        }
        if (ObjectUtil.isNotEmpty(bizApprovalOrderPageParam.getStartPayTime()) && ObjectUtil.isNotEmpty(bizApprovalOrderPageParam.getEndPayTime())) {
            queryWrapper.lambda().between(BizApprovalOrder::getPayTime, bizApprovalOrderPageParam.getStartPayTime(), bizApprovalOrderPageParam.getEndPayTime());
        }
        if (ObjectUtil.isNotEmpty(bizApprovalOrderPageParam.getApplicantName())) {
            queryWrapper.lambda().like(BizApprovalOrder::getApplicantName, bizApprovalOrderPageParam.getApplicantName());
        }
        if (ObjectUtil.isNotEmpty(bizApprovalOrderPageParam.getApplicantDeptName())) {
            queryWrapper.lambda().like(BizApprovalOrder::getApplicantDeptName, bizApprovalOrderPageParam.getApplicantDeptName());
        }
        if (ObjectUtil.isNotEmpty(bizApprovalOrderPageParam.getVisitDeptName())) {
            queryWrapper.lambda().like(BizApprovalOrder::getVisitDeptName, bizApprovalOrderPageParam.getVisitDeptName());
        }
        if (ObjectUtil.isNotEmpty(bizApprovalOrderPageParam.getVisitCafeteriaName())) {
            queryWrapper.lambda().like(BizApprovalOrder::getVisitCafeteriaName, bizApprovalOrderPageParam.getVisitCafeteriaName());
        }
        if (ObjectUtil.isNotEmpty(bizApprovalOrderPageParam.getPayType())) {
            queryWrapper.lambda().eq(BizApprovalOrder::getPayType, bizApprovalOrderPageParam.getPayType());
        }
        if (ObjectUtil.isNotEmpty(bizApprovalOrderPageParam.getCafeteriaType())) {
            queryWrapper.lambda().eq(BizApprovalOrder::getCafeteriaType, bizApprovalOrderPageParam.getCafeteriaType());
        }


        if (ObjectUtil.isAllNotEmpty(bizApprovalOrderPageParam.getSortField(), bizApprovalOrderPageParam.getSortOrder())) {
            CommonSortOrderEnum.validate(bizApprovalOrderPageParam.getSortOrder());
            queryWrapper.orderBy(true, bizApprovalOrderPageParam.getSortOrder().equals(CommonSortOrderEnum.ASC.getValue()),
                    StrUtil.toUnderlineCase(bizApprovalOrderPageParam.getSortField()));
        } else {
            queryWrapper.lambda().orderByDesc(BizApprovalOrder::getPayTime);
        }
        return this.page(CommonPageRequest.defaultPage(), queryWrapper);
    }

    @Override
    public Page<BizApprovalOrder> userApprovalOrderPage(BizUserApprovalOrderPageParam bizApprovalOrderPageParam) {
        QueryWrapper<BizApprovalOrder> queryWrapper = new QueryWrapper<BizApprovalOrder>().checkSqlInjection();
        queryWrapper.lambda().eq(BizApprovalOrder::getApplicantId, StpUtil.getLoginIdAsString());
        queryWrapper.lambda().eq(BizApprovalOrder::getPayType, BizApprovalPayTypeEnum.TRUE.getValue());
        if (ObjectUtil.isAllNotEmpty(bizApprovalOrderPageParam.getSortField(), bizApprovalOrderPageParam.getSortOrder())) {
            CommonSortOrderEnum.validate(bizApprovalOrderPageParam.getSortOrder());
            queryWrapper.orderBy(true, bizApprovalOrderPageParam.getSortOrder().equals(CommonSortOrderEnum.ASC.getValue()),
                    StrUtil.toUnderlineCase(bizApprovalOrderPageParam.getSortField()));
        } else {
            queryWrapper.lambda().orderByDesc(BizApprovalOrder::getPayTime);
        }
        return this.page(CommonPageRequest.defaultPage(), queryWrapper);
    }

    @Override
    public Page<BizApprovalOrder> canteenApprovalOrderPage(BizUserApprovalOrderPageParam bizApprovalOrderPageParam) {
        QueryWrapper<BizApprovalOrder> queryWrapper = new QueryWrapper<BizApprovalOrder>().checkSqlInjection();
        SaBaseLoginUser loginUser = StpLoginUserUtil.getLoginUser();
        queryWrapper.lambda().eq(BizApprovalOrder::getVisitCafeteriaId, loginUser.getCanteenId());
        queryWrapper.lambda().eq(BizApprovalOrder::getPayType, BizApprovalPayTypeEnum.TRUE.getValue());
        if (ObjectUtil.isAllNotEmpty(bizApprovalOrderPageParam.getSortField(), bizApprovalOrderPageParam.getSortOrder())) {
            CommonSortOrderEnum.validate(bizApprovalOrderPageParam.getSortOrder());
            queryWrapper.orderBy(true, bizApprovalOrderPageParam.getSortOrder().equals(CommonSortOrderEnum.ASC.getValue()),
                    StrUtil.toUnderlineCase(bizApprovalOrderPageParam.getSortField()));
        } else {
            queryWrapper.lambda().orderByDesc(BizApprovalOrder::getPayTime);
        }
        return this.page(CommonPageRequest.defaultPage(), queryWrapper);
    }

    @Override
    public BizApprovalOrder detail(BizApprovalOrderIdParam bizApprovalOrderIdParam) {
        return this.queryEntity(bizApprovalOrderIdParam.getId());
    }

    @Override
    public BizApprovalOrder queryEntity(String id) {
        BizApprovalOrder bizApprovalOrder = this.getById(id);
        if (ObjectUtil.isEmpty(bizApprovalOrder)) {
            throw new CommonException("签到支付记录不存在，id值为：{}", id);
        }
        return bizApprovalOrder;
    }

    @Resource
    private BizApprovalService bizApprovalService;
    @Resource
    private BizCanteenService bizCanteenService;

    /**
     * 当前时间所在就餐时间段内
     */
    private BizApprovalCafeteriaTypeEnum eat(BizApproval approval) {
        LocalTime nowTime = LocalTime.now();
        if (!CommonSwitchEnum.isTrue(approval.getIsLunchEat()) && ObjectUtil.isNotEmpty(approval.getVisitLunchCafeteriaId())) {
            BizCanteen canteen = bizCanteenService.queryEntity(approval.getVisitLunchCafeteriaId());
            if (nowTime.isAfter(canteen.getLunchBeginTime().toLocalTime()) && nowTime.isBefore(canteen.getLunchEndTime().toLocalTime())) {
                return BizApprovalCafeteriaTypeEnum.LUNCH;
            }
        }
        if (!CommonSwitchEnum.isTrue(approval.getIsSupperEat()) && ObjectUtil.isNotEmpty(approval.getVisitSupperCafeteriaId())) {
            BizCanteen canteen = bizCanteenService.queryEntity(approval.getVisitSupperCafeteriaId());
            if (nowTime.isAfter(canteen.getDinerBeginTime().toLocalTime()) && nowTime.isBefore(canteen.getDinerEndTime().toLocalTime())) {
                return BizApprovalCafeteriaTypeEnum.SUPPER;
            }
        }
        throw new CommonException("当前时间不在就餐时间段内");
    }

    /**
     * 创建吃饭订单
     *
     * @param bizApprovalCreateOrderParam
     */
    @Transactional
    public BizApprovalOrder createOrder(BizApprovalCreateOrderParam bizApprovalCreateOrderParam) {
        String approvalId = bizApprovalCreateOrderParam.getApprovalId();
        BizApproval approval = bizApprovalService.queryEntity(approvalId);
        SaBaseLoginUser loginUser = StpLoginUserUtil.getLoginUser();
        if (!Objects.equals(approval.getApplicantId(), loginUser.getId())) {
            throw new CommonException("无权限操作");
        }
        if (!Objects.equals(approval.getApprovalStatus(), BizApprovalEnum.WAIT_VISIT.getValue())) {
            throw new CommonException("审批单未通过，无法生成订单");
        }
        //=====
        BizApprovalCafeteriaTypeEnum cafeteriaType = eat(approval);
        String visitCafeteriaId;
        String visitCafeteriaName;
        BigDecimal cafeteriaPrice;
        if (Objects.equals(cafeteriaType, BizApprovalCafeteriaTypeEnum.LUNCH)) {
            visitCafeteriaId = approval.getVisitLunchCafeteriaId();
            visitCafeteriaName = approval.getVisitLunchCafeteriaName();
            cafeteriaPrice = approval.getLunchPrice();
        } else {
            visitCafeteriaId = approval.getVisitSupperCafeteriaId();
            visitCafeteriaName = approval.getVisitSupperCafeteriaName();
            cafeteriaPrice = approval.getSupperPrice();
        }
        // 生成订单
        BizApprovalOrder saveOrder = new BizApprovalOrder();
        saveOrder.setApprovalId(loginUser.getId());
        String orderSn = IdUtil.getSnowflakeNextIdStr();
        saveOrder.setOrderSn(orderSn);
        saveOrder.setVisitDeptId(approval.getVisitDeptId());
        saveOrder.setVisitDeptName(approval.getVisitDeptName());
        saveOrder.setVisitCafeteriaId(visitCafeteriaId);
        saveOrder.setVisitCafeteriaName(visitCafeteriaName);
        saveOrder.setApprovalId(approval.getId());
        saveOrder.setCafeteriaType(cafeteriaType.getValue());
        saveOrder.setCafeteriaPrice(cafeteriaPrice);
        saveOrder.setPayType(BizApprovalPayTypeEnum.FALSE.getValue());//默认已支付
        saveOrder.setApplicantDeptId(loginUser.getOrgId());
        saveOrder.setApplicantDeptName(loginUser.getOrgName());
        saveOrder.setApplicantId(loginUser.getId());
        saveOrder.setApplicantName(loginUser.getName());
        this.save(saveOrder);
        return saveOrder;
    }


    public List<BizApprovalDeptResult> deptList(BizApprovalDeptPageParam bizApprovalDeptPageParam) {
        return this.baseMapper.deptList(bizApprovalDeptPageParam.getStartPayTime(), bizApprovalDeptPageParam.getEndPayTime());
    }

    public List<BizApprovalCanteenResult> canteenOrderList(BizApprovalCanteenOrderPageParam bizApprovalCanteenOrderPageParam) {
        return this.baseMapper.canteenOrderList(bizApprovalCanteenOrderPageParam.getStartPayTime(),
                bizApprovalCanteenOrderPageParam.getEndPayTime(),
                bizApprovalCanteenOrderPageParam.getCanteenName());
    }


    public ResponseEntity<byte[]> exportCanteenOrderList(BizApprovalCanteenOrderPageParam bizApprovalCanteenOrderPageParam) {
        List<BizApprovalCanteenResult> data = canteenOrderList(bizApprovalCanteenOrderPageParam);

        try (Workbook workbook = new XSSFWorkbook();
             ByteArrayOutputStream out = new ByteArrayOutputStream()) {

            Sheet sheet = workbook.createSheet("Department Report");
            // 创建表头
            Row header = sheet.createRow(0);
            String[] headers = {"部门唯一标识","食堂名称", "订单数量", "部门金额"};
            for (int i = 0; i < headers.length; i++) {
                header.createCell(i).setCellValue(headers[i]);
            }

            // 填充数据
            int rowNum = 1;
            for (BizApprovalCanteenResult record : data) {
                Row row = sheet.createRow(rowNum++);
                row.createCell(0).setCellValue(record.getCanteenId());
//                row.createCell(1).setCellValue(record.getDeptName());
                row.createCell(1).setCellValue(record.getCanteenName());
                row.createCell(2).setCellValue(record.getTotalOrders());
                row.createCell(3).setCellValue(record.getTotalCafeteriaPrice().doubleValue());
            }

            // 自动调整列宽
            for (int i = 0; i < headers.length; i++) {
                sheet.autoSizeColumn(i);
            }

            workbook.write(out);

            HttpHeaders responseHeaders = new HttpHeaders();
            responseHeaders.add("Content-Disposition", "attachment; filename=部门报表_" +
                    LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")) + ".xlsx");
            return new ResponseEntity<>(out.toByteArray(), responseHeaders, HttpStatus.OK);

        } catch (IOException e) {
            throw new RuntimeException("导出Excel失败", e);
        }
    }


    public ResponseEntity<byte[]> exportDeptList(BizApprovalDeptPageParam bizApprovalDeptPageParam) {
        List<BizApprovalDeptResult> data = deptList(bizApprovalDeptPageParam);

        try (Workbook workbook = new XSSFWorkbook();
             ByteArrayOutputStream out = new ByteArrayOutputStream()) {

            Sheet sheet = workbook.createSheet("Department Report");
            // 创建表头
            Row header = sheet.createRow(0);
            String[] headers = {"部门唯一标识", "部门名称", "订单数量", "部门金额"};
            for (int i = 0; i < headers.length; i++) {
                header.createCell(i).setCellValue(headers[i]);
            }

            // 填充数据
            int rowNum = 1;
            for (BizApprovalDeptResult record : data) {
                Row row = sheet.createRow(rowNum++);
                row.createCell(0).setCellValue(record.getApplicantDeptId());
                row.createCell(1).setCellValue(record.getApplicantDeptName());
                row.createCell(2).setCellValue(record.getTotalOrders());
                row.createCell(3).setCellValue(record.getTotalCafeteriaPrice().doubleValue());
            }

            // 自动调整列宽
            for (int i = 0; i < headers.length; i++) {
                sheet.autoSizeColumn(i);
            }

            workbook.write(out);

            HttpHeaders responseHeaders = new HttpHeaders();
            responseHeaders.add("Content-Disposition", "attachment; filename=部门报表_" +
                    LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")) + ".xlsx");
            return new ResponseEntity<>(out.toByteArray(), responseHeaders, HttpStatus.OK);

        } catch (IOException e) {
            throw new RuntimeException("导出Excel失败", e);
        }
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<BizApprovalOrderIdParam> bizApprovalOrderIdParamList) {
        // 执行删除
        this.removeByIds(CollStreamUtil.toList(bizApprovalOrderIdParamList, BizApprovalOrderIdParam::getId));
    }


}
